package com.itheima.sfbx.insurance.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.sfbx.framework.commons.constant.basic.SuperConstant;
import com.itheima.sfbx.framework.commons.constant.insure.InsureConstant;
import com.itheima.sfbx.framework.commons.dto.basic.TreeItemVO;
import com.itheima.sfbx.framework.commons.dto.basic.TreeVO;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.NoProcessing;
import com.itheima.sfbx.insurance.dto.CategoryCoefficentVO;
import com.itheima.sfbx.insurance.dto.CategoryConditionVO;
import com.itheima.sfbx.insurance.dto.CategorySafeguardVO;
import com.itheima.sfbx.insurance.dto.CategoryVO;
import com.itheima.sfbx.insurance.enums.CategoryEnum;
import com.itheima.sfbx.insurance.mapper.CategoryMapper;
import com.itheima.sfbx.insurance.pojo.Category;
import com.itheima.sfbx.insurance.pojo.CategoryCoefficent;
import com.itheima.sfbx.insurance.pojo.CategoryCondition;
import com.itheima.sfbx.insurance.pojo.CategorySafeguard;
import com.itheima.sfbx.insurance.service.ICategoryCoefficentService;
import com.itheima.sfbx.insurance.service.ICategoryConditionService;
import com.itheima.sfbx.insurance.service.ICategorySafeguardService;
import com.itheima.sfbx.insurance.service.ICategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description：保险分类服务实现类
 */
@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

    @Autowired
    ICategoryConditionService categoryConditionService;

    @Autowired
    ICategoryCoefficentService categoryCoefficentService;

    @Autowired
    ICategorySafeguardService categorySafeguardService;


    private LambdaQueryWrapper<Category> queryWrapper(CategoryVO vo) {
        LambdaQueryWrapper<Category> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StrUtil.isNotBlank(vo.getParentCategoryNo()), Category::getParentCategoryNo, vo.getParentCategoryNo());
        lqw.eq(StrUtil.isNotBlank(vo.getCategoryNo()), Category::getCategoryNo, vo.getCategoryNo());
        lqw.like(StrUtil.isNotBlank(vo.getCategoryName()), Category::getCategoryName, vo.getCategoryName());
        lqw.eq(StrUtil.isNotBlank(vo.getCategoryType()), Category::getCategoryType, vo.getCategoryType());
        lqw.eq(StrUtil.isNotBlank(vo.getDataState()), Category::getDataState, vo.getDataState());
        lqw.eq(StrUtil.isNotBlank(vo.getLeafNode()), Category::getLeafNode, vo.getLeafNode());
        lqw.eq(StrUtil.isNotBlank(vo.getShowIndex()), Category::getShowIndex, vo.getShowIndex());
        return lqw;
    }


    private void buildVoList(List<CategoryVO> voList) {
        Set<String> noSet = voList.stream().map(CategoryVO::getCategoryNo).collect(Collectors.toSet());
        //处理condition
        List<CategoryCondition> conditionList = categoryConditionService.lambdaQuery()
                .in(CategoryCondition::getCategoryNo, noSet)
                .list();
        Map<String, List<CategoryCondition>> conditionMap = conditionList.stream().collect(Collectors.groupingBy(CategoryCondition::getCategoryNo));
        //处理coefficent
        List<CategoryCoefficent> coefficentList = categoryCoefficentService.lambdaQuery().in(CategoryCoefficent::getCategoryNo, noSet).list();
        Map<String, List<CategoryCoefficent>> coefficentMap = coefficentList.stream().collect(Collectors.groupingBy(CategoryCoefficent::getCategoryNo));
        //处理safeguard
        List<CategorySafeguard> safeguardList = categorySafeguardService.lambdaQuery().in(CategorySafeguard::getCategoryNo, noSet).list();
        Map<String, List<CategorySafeguard>> safeguardMap = safeguardList.stream().collect(Collectors.groupingBy(CategorySafeguard::getCategoryNo));

        for (CategoryVO vo : voList) {
//            //严禁在循环中访问数据库
//            List<CategoryCondition> conditionList1 = categoryConditionService.lambdaQuery().eq(CategoryCondition::getCategoryNo, vo.getCategoryNo()).list();
//
//            for (CategoryCoefficent coefficent : coefficentList) {
//                if (vo.getCategoryNo().equals(coefficent.getCategoryNo())) {
//                    List<CategoryCoefficentVO> coefficentVOs = vo.getCategoryCoefficentVOs();
//                    if(coefficentVOs==null){
//                        coefficentVOs = new ArrayList<>();
//                    }
//                    coefficentVOs.add(BeanConv.toBean(coefficent, CategoryCoefficentVO.class));
//                }
//            }
            List<CategoryCondition> conditions = conditionMap.get(vo.getCategoryNo());
            vo.setCategoryConditionVOs(BeanConv.toBeanList(conditions, CategoryConditionVO.class));
            List<CategoryCoefficent> coefficents = coefficentMap.get(vo.getCategoryNo());
            vo.setCategoryCoefficentVOs(BeanConv.toBeanList(coefficents, CategoryCoefficentVO.class));
            List<CategorySafeguard> safeguards = safeguardMap.get(vo.getCategoryNo());
            vo.setCategorySafeguardVOs(BeanConv.toBeanList(safeguards, CategorySafeguardVO.class));
        }

    }

    @Override
    public Page<CategoryVO> findPage(CategoryVO categoryVO, int pageNum, int pageSize) {
        //分页
        Page<Category> page = this.page(new Page<>(pageNum, pageSize), queryWrapper(categoryVO));
        Page<CategoryVO> voPage = BeanConv.toPage(page, CategoryVO.class);
        List<CategoryVO> records = voPage.getRecords();
        if (CollUtil.isEmpty(records)) {
            return voPage;
        }
        buildVoList(records);
        return voPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CategoryVO save(CategoryVO categoryVO) {
        //添加分类
        String parentCategoryNo = categoryVO.getParentCategoryNo();
        Category bean = this.lambdaQuery().eq(Category::getCategoryNo, parentCategoryNo).one();
        if(bean==null){
            throw new ProjectException(CategoryEnum.SAVE_FAIL);  //找不到对应的父节点，参数错误
        }
        Category category = BeanConv.toBean(categoryVO, Category.class);

        String categoryNo = this.createCategoryNo(parentCategoryNo);
        category.setCategoryNo(categoryNo);
        this.save(category);
        return BeanConv.toBean(category,CategoryVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(CategoryVO categoryVO) {
        //修改 1.改分类对象 2.改分类对象的系数项，筛选项，保障项
        //健壮性判断
        Category bean = getById(categoryVO.getId());
        if (bean == null) {
            throw new ProjectException(CategoryEnum.UPDATE_FAIL);
        }
        //改分类对象
        Category category = BeanConv.toBean(categoryVO, Category.class);
        this.updateById(category);

        //改分类对象的系数项，筛选项，保障项 (先删再加)
        categoryConditionService.deleteByCategoryNo(categoryVO.getCategoryNo());
        categoryCoefficentService.deleteByCategoryNo(categoryVO.getCategoryNo());
        categorySafeguardService.deleteByCategoryNo(categoryVO.getCategoryNo());

        List<CategoryCoefficentVO> categoryCoefficentVOs = categoryVO.getCategoryCoefficentVOs();
        if (CollUtil.isNotEmpty(categoryCoefficentVOs)) {
            categoryCoefficentVOs.forEach(c -> c.setCategoryNo(categoryVO.getCategoryNo()));
            categoryCoefficentService.saveBatch(BeanConv.toBeanList(categoryCoefficentVOs, CategoryCoefficent.class));
        }

        List<CategoryConditionVO> categoryConditionVOs = categoryVO.getCategoryConditionVOs();
        if (CollUtil.isNotEmpty(categoryConditionVOs)) {
            categoryConditionVOs.forEach(c -> c.setCategoryNo(categoryVO.getCategoryNo()));
            categoryConditionService.saveBatch(BeanConv.toBeanList(categoryConditionVOs, CategoryCondition.class));
        }

        List<CategorySafeguardVO> categorySafeguardVOs = categoryVO.getCategorySafeguardVOs();
        if (CollUtil.isNotEmpty(categorySafeguardVOs)) {
            categorySafeguardVOs.forEach(c -> c.setCategoryNo(categoryVO.getCategoryNo()));
            categorySafeguardService.saveBatch(BeanConv.toBeanList(categorySafeguardVOs, CategorySafeguard.class));
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(String[] checkedIds) {
        //删除分类
        //健壮性判断
        List<Category> categories = this.listByIds(Arrays.asList(checkedIds));
        if(categories.size()!=checkedIds.length  || CollUtil.isEmpty(categories)){
            throw new ProjectException(CategoryEnum.DEL_FAIL);  //存在非法参数，传过来的id的数量应该与数据库查到的分类数量相同
        }
        //先删除本类，再删除关系类
        this.removeByIds(Arrays.asList(checkedIds));

        List<String> caNos = categories.stream().map(Category::getCategoryNo).collect(Collectors.toList());
        Integer count = categorySafeguardService.lambdaQuery().in(CategorySafeguard::getCategoryNo, caNos)
                .count();
        if(count>0){
            LambdaQueryWrapper<CategorySafeguard> queryWrapper = new LambdaQueryWrapper<CategorySafeguard>().in(CategorySafeguard::getCategoryNo,caNos);
            categorySafeguardService.remove(queryWrapper);
        }
        Integer count1 = categoryConditionService.lambdaQuery().in(CategoryCondition::getCategoryNo, caNos)
                .count();
        if(count1>0){
            LambdaQueryWrapper<CategoryCondition> queryWrapper = new LambdaQueryWrapper<CategoryCondition>().in(CategoryCondition::getCategoryNo,caNos);
            categoryConditionService.remove(queryWrapper);
        }
        Integer count2 = categoryCoefficentService.lambdaQuery().in(CategoryCoefficent::getCategoryNo, caNos)
                .count();
        if(count2>0){
            LambdaQueryWrapper<CategoryCoefficent> queryWrapper = new LambdaQueryWrapper<CategoryCoefficent>().in(CategoryCoefficent::getCategoryNo,caNos);
            categoryCoefficentService.remove(queryWrapper);
        }
        return true;
    }

    @Override
    public List<CategoryVO> findList(CategoryVO categoryVO) {
        //查询集合
        List<Category> categoryList = this.list(queryWrapper(categoryVO));
        if (CollUtil.isEmpty(categoryList)) {
            throw new ProjectException(CategoryEnum.LIST_FAIL);
        }
        List<CategoryVO> categoryVOList = BeanConv.toBeanList(categoryList, CategoryVO.class);
        List<Long> nodeFloors = categoryVO.getNodeFloors();
        if (CollUtil.isNotEmpty(nodeFloors)) {
            categoryVOList = categoryVOList.stream().filter(vo -> {
                Long level = (long) (NoProcessing.processString(vo.getCategoryNo()).length() / 3 - 1);
                return nodeFloors.contains(level);
            }).collect(Collectors.toList());
        }
        buildVoList(categoryVOList);
       /* categoryVOList = categoryVOList.stream().filter(vo->
             nodeFloors.contains((long) (NoProcessing.processString(vo.getCategoryNo()).length() / 3 - 1))
        ).collect(Collectors.toList());*/
        return categoryVOList;
    }


    @Override
    public TreeVO categoryTreeVO(String parentCategoryNo, String categoryType, String[] checkedCategoryNos) {
        //先确定根节点
        String rootNo = StrUtil.isBlank(parentCategoryNo) ? SuperConstant.ROOT_PARENT_ID : parentCategoryNo;
        String string = NoProcessing.processString(rootNo);
        //找出根节点下所有的子节点
        List<Category> categoryList = this.lambdaQuery()
                .likeRight(Category::getCategoryNo, string)
                .eq(StrUtil.isNotBlank(categoryType), Category::getCategoryType, categoryType)
                .list();
        //健壮性判断,为空，返回空集合
        if (CollUtil.isEmpty(categoryList)) {
            return TreeVO.builder().build();
        }
        //将List<Category>转为List<TreeItemVO> 集合
        List<TreeItemVO> treeItemVOList = categoryList.stream().map(c -> TreeItemVO.builder().id(c.getCategoryNo()).parentId(c.getParentCategoryNo()).label(c.getCategoryName()).build())
                .collect(Collectors.toList());
        //转为key为ParentCategoryNo，value为TreeItemVO对象的map集合
        Map<String, List<TreeItemVO>> treeMap = treeItemVOList.stream().collect(Collectors.groupingBy(TreeItemVO::getParentId));
        //挂上关系
        //遍历
        for (TreeItemVO treeItemVO : treeItemVOList) {
            List<TreeItemVO> treeItemVoList1 = treeMap.get(treeItemVO.getId());
            treeItemVO.setChildren(treeItemVoList1);
        }
        //构建这个treevo对象
        TreeVO build = TreeVO.builder()
                .items(treeMap.get(rootNo))
                .build();
        return build;
    }

    @Override
    public String createCategoryNo(String parentCategoryNo) {
        CategoryVO categoryVO = CategoryVO.builder()
                .parentCategoryNo(parentCategoryNo)
                .build();
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Category::getParentCategoryNo, parentCategoryNo);
        List<Category> categoryList = list(queryWrapper);
        //无下属节点则创建下属节点
        if (EmptyUtil.isNullOrEmpty(categoryList)) {
            return NoProcessing.createNo(parentCategoryNo, false);
            //有下属节点则累加下属节点
        } else {
            Long categoryNo = categoryList.stream()
                    .map(category -> {
                        return Long.valueOf(category.getCategoryNo());
                    })
                    .max(Comparator.comparing(i -> i)).get();
            return NoProcessing.createNo(String.valueOf(categoryNo), true);
        }
    }

    /**
     * 人种榜险种榜分类
     *
     * @param type
     */
    @Override
    public List<CategoryVO> categoryCheckRule(String type) {
        //判断是否是险种榜
        if (InsureConstant.checkIsInsureType(type)) {
            List<CategoryVO> res = new ArrayList<>();
            //获取所有的险种榜
            List<String> allCheckRule = InsureConstant.getAllCheckRule();
            allCheckRule.forEach(e -> {
                CategoryVO categoryVO = CategoryVO.builder().categoryNo(e).categoryName(InsureConstant.getRuleNameById(e)).build();
                res.add(categoryVO);
            });
            return res;
        } else {
            //说明是人种榜
            List<String> categoryNames = Arrays.asList("成年人", "少儿", "老人");
            LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(Category::getCategoryName, categoryNames);
            queryWrapper.eq(Category::getDataState, SuperConstant.DATA_STATE_0);
            List<CategoryVO> res = BeanConv.toBeanList(list(queryWrapper), CategoryVO.class);
            return res;
        }
    }
}
